/**********************************************************************************
 * Code license:  GNU General Public License v3                                   *
 * Main page:     https://code.google.com/p/library-cross-platform/               *
 * Issue tracker: https://code.google.com/p/library-cross-platform/issues/list    *
***********************************************************************************/

package library.classloader;

import java.lang.reflect.*;
import java.util.*;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class ClassLoad {
  private Hashtable        loadedClasses = new Hashtable();

  public ClassLoad() {
  }

  protected synchronized Class loadClass(String className) throws ClassNotFoundException {
	Class       result     = null;
    ClassLoader cl         = null;
    
    result = (Class)loadedClasses.get(className);
    if(result != null)
     return result;
	  
    cl = ClassLoad.class.getClassLoader();
    result = cl.loadClass(className);

    if (result == null)
     throw new ClassNotFoundException();

    loadedClasses.put(className, result);
    return result;
  }

  public Object getClass(StringBuilder className) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    return getClass(className);
  }

  public Object getClass(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException {
    Class  cl = null;
    Object obj = null;
    int index = 1;
    String[] splits = className.split("\\$");
    String objName;
    cl = loadClass(splits[0]);
    obj = cl.newInstance();
    if(splits.length == 1)
     return obj;
    
    objName = splits[0];
    while (index < splits.length) {
      objName = objName + "$" + splits[index++];
      for (Class<?> cls : obj.getClass().getDeclaredClasses()) {
        if(cls.getName().equals(objName)) {
          obj = getClass(objName, cls, obj);
        }
      }
    }
    
    return obj;
  }

  protected Object getClass(String className, Class cls, Object parentObj) throws ClassNotFoundException,
                                                                               InvocationTargetException,
                                                                               InstantiationException,
                                                                               IllegalAccessException,
                                                                               NoSuchMethodException,
                                                                               SecurityException {
    Object obj = null;
    if (!Modifier.isStatic(cls.getModifiers())) {
     // This is an inner class. Pass the parent class in.
       obj = cls.getDeclaredConstructor(new Class[] { parentObj.getClass() }).newInstance(new Object[] { parentObj });
     } else {
         // This is a nested class. You can also use it here as follows:
       obj = cls.getDeclaredConstructor(new Class[] {}).newInstance(new Object[] {});
     }

    return obj;
  }
}
